﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Warensoft.Utility;
using System.IO;
using Warensoft.Socket.MessageDataStructs;
using Warensoft.Socket.EventArgs;
using System.Threading.Tasks;

namespace Warensoft.Socket
{
    public abstract  class Channel:IDisposable 
    {
        public string Name { get; set; }
        /// <summary>
        /// 该Channel内的用户列表
        /// </summary>
        protected  List<ClientSessionBase> clients = new List<ClientSessionBase>();
        public List<ClientSessionBase> Clients
        {
            get
            {
                return this.clients;
            }
        }
        /// <summary>
        /// 该Channel所属的SocketServer
        /// </summary>
        protected SocketServer server = null;
        private bool needBreak = false;
        /// <summary>
        /// 当频道为空时触发
        /// </summary>
        public static  event EventHandler ChannelEmpty;
        /// <summary>
        /// 当新频道被创建时被触发
        /// </summary>
        public static event EventHandler NewChannel;
        /// <summary>
        /// 构造方法
        /// </summary>
        /// <param name="name">频道的名称</param>
        protected  Channel(string name)
        {
            this.Name = name;
            if (NewChannel != null)
            {
                NewChannel(this, new System.EventArgs());
            }
        }
        /// <summary>
        /// 构造方法
        /// </summary>
        /// <param name="name">频道的名称</param>
        /// <param name="server">该Channel所属的SocketServer</param>
        protected Channel(string name,SocketServer server)
        {
            this.Name = name;
            this.server = server;
            if (NewChannel != null)
            {
                NewChannel(this, new System.EventArgs());
            }
        }
        /// <summary>
        /// 加入Channel
        /// </summary>
        /// <param name="client">客户Session</param>
        public void AddSession(ClientSessionBase client)
        {
            if (this.clients !=null )
            {
                this.needBreak = true;
                this.clients.Add(client);
                client.Disconnected += new EventHandler<DisconnectedEventArgs>(client_Disconnected);
                this.needBreak = false; 
            }
        }

        void client_Disconnected(object sender, DisconnectedEventArgs e)
        {
            this.RemoveSession(sender as ClientSessionBase);    
        }
        private bool channelEmptyLock = false;
        /// <summary>
        /// 移除用户
        /// </summary>
        /// <param name="client">客户Session</param>
        public void RemoveSession(ClientSessionBase client)
        {
            lock (this)
            {
                if (this.clients != null && this.clients.Count != 0)
                {
                    this.needBreak = true;
                    this.clients.Remove(client);
                    this.OnSessionRemoved(client );
                    if (this.channelEmptyLock == false && this.clients.Count == 0)
                    {
                        this.channelEmptyLock = true;
                        this.OnRoomEmpty();
                        if (ChannelEmpty != null)
                        {

                            ChannelEmpty(this, new System.EventArgs());
                        }
                    }
                    this.needBreak = false;
                } 
            }
            
        }
        public abstract void OnSessionRemoved(ClientSessionBase session);
        protected abstract void OnRoomEmpty();
        /// <summary>
        /// 广播消息
        /// </summary>
        /// <param name="message">消息内容</param>
        public void BroadCast(MemoryStream message)
        {
            if (this.clients != null && this.clients.Count() != 0)
            {
                var clientArray = this.clients.ToArray();
                var length = clientArray.Length;
                Parallel.For(0, length, i =>
                {
                    if (this.needBreak)
                    {
                        return;
                    }
                    else
                    {
                        //clientArray[i].SendMessage(message); 
                        if (clientArray[i] != null && clientArray[i].SocketDisconnected == false)
                        {
                            clientArray[i].SendMessage(message as PackageBase);
                        }
                    }
                }
                );
                //for (int i = 0; i < length; i++)
                //{
                //    if (this.needBreak)
                //    {
                //        return;
                //    }
                //    else
                //    {
                //        //clientArray[i].SendMessage(message); 
                //        if (clientArray[i] != null && clientArray[i].SocketDisconnected == false)
                //        {
                //            clientArray[i].SendMessage(message as PackageBase);
                //        }
                //    }
                //}
            }
        }

        #region IDisposable Members

        public void Dispose()
        {
            this.clients.Clear();
            this.clients = null;
            
        }

        #endregion
    }
}
